﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEngine;

namespace HDJ.Framework.Core
{
    /// <summary>
    /// 游戏运行模式
    /// </summary>
    public enum GameRunType
    {
        /// <summary>
        /// 开发版本
        /// </summary>
        Developing,
        /// <summary>
        /// 发布版本
        /// </summary>
        Release,
    }
    public  class ApplicationManager:MonoBehaviour
    {

        private static Dictionary<Type, AppModuleBase> allModules = new Dictionary<Type, AppModuleBase>();

        public static CallBack OnUpdate;
        public static CallBack OnFixedUpdate;
        public static CallBack OnLateUpdate;
        public static CallBack OnGUIUpdate;
        public static CallBack OnDrawGizmosUpdate;
        public static CallBack OnApplicationExit;

        private static GameRunType m_gameRunType = GameRunType.Developing;
        public static GameRunType GameRunType
        {
            get
            {
                return m_gameRunType;
            }
        }

        // [RuntimeInitializeOnLoadMethod]
        private static bool isInit = false;
        private  void Awake()
        {
            if (isInit)
                return;
            isInit = true;

            Boot();
           
            MonoBehaviourRuntime.Instance.OnUpdate += OnUpdateExcute;
            MonoBehaviourRuntime.Instance.OnFixedUpdate += OnFixedUpdateExcute;
            MonoBehaviourRuntime.Instance.OnLateUpdate += OnLateUpdateExcute;
            MonoBehaviourRuntime.Instance.OnGUIUpdate += OnGUIUpdateExcute;
            MonoBehaviourRuntime.Instance.OnDrawGizmosUpdate += OnDrawGizmosUpdateExcute;
            MonoBehaviourRuntime.Instance.OnApplicationExit += OnApplicationExitExcute;

        }

        private void Boot()
        {
            GameBootConfig config = GameBootConfig.LoadConfig();

            if (config == null)
            {
                Debug.LogWarning("GameFrameworkConfig is null");
                config = new GameBootConfig();
                config.gameRunType = GameRunType.Developing;
            }
            m_gameRunType = config.gameRunType;
            Application.runInBackground = config.runInBackground;


            Type[] types = ReflectionUtils.GetChildTypes(typeof(AppModuleBase));
            List<AppModuleBase> modules = new List<AppModuleBase>();
            foreach (var type in types)
            {
                if (type.IsAbstract)
                {
                    continue;
                }

                AppModuleBase appModule = (AppModuleBase)ReflectionUtils.CreateDefultInstance(type);
                allModules.Add(type, appModule);
                //Debug.Log("Initialize ModuleName:" + appModule.GetModuleName() + " Version:" + appModule.GetModuleVersion());
                if (config.allAppModuleSetting.ContainsKey(type.Name))
                {
                    appModule = (AppModuleBase)config.allAppModuleSetting[type.Name].GetValue(appModule);
                    if (!appModule.Enable)
                    {
                        continue;
                    }

                    modules.Add(appModule);
                }
            }
            foreach (var appModule in modules)
            {
                try
                {
                    appModule.OnCreate();
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                }
            }
            foreach (var appModule in modules)
            {
                try
                {
                    appModule.OnStart();
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                }
            }
            foreach (var appModule in modules)
            {
                try
                {
                    appModule.OnEnable();
                }
                catch (Exception e)
                {
                    Debug.LogError(e);
                }
            }
        }
       
        #region 生命周期
        private static void OnFixedUpdateExcute()
        {
            foreach (var item in allModules.Values)
            {
                if (item.Enable)
                {
                    item.OnFixedUpdate();
                }
            }
            if (OnFixedUpdate != null)
                OnFixedUpdate();
        }

        private static void OnUpdateExcute()
        {
            foreach (var item in allModules.Values)
            {
                if (item.Enable)
                {
                    item.OnUpdate();
                }
            }
            if (OnUpdate != null)
                OnUpdate();
        }
        private static void OnLateUpdateExcute()
        {
            foreach (var item in allModules.Values)
            {
                if (item.Enable)
                {
                    item.OnLateUpdate();
                }
            }
            if (OnLateUpdate != null)
                OnLateUpdate();
        }
        private static void OnDrawGizmosUpdateExcute()
        {
            foreach (var item in allModules.Values)
            {
                if (item.Enable)
                {
                    item.OnDrawGizmosUpdate();
                }
            }
            if (OnDrawGizmosUpdate != null)
                OnDrawGizmosUpdate();
        }
        private static void OnGUIUpdateExcute()
        {
            foreach (var item in allModules.Values)
            {
                if (item.Enable)
                {
                    item.OnGUIUpdate();
                }
            }
            if (OnGUIUpdate != null)
                OnGUIUpdate();
        }
        private static void OnApplicationExitExcute()
        {
            foreach (var item in allModules.Values)
            {
                if (item.Enable)
                {
                    item.OnDisable();
                    item.OnApplicationQuit();
                }
            }
            if (OnApplicationExit != null)
                OnApplicationExit();
        }
    }
    #endregion
}
